const express = require('express');
const cors = require('cors');
const sqlite3 = require('sqlite3').verbose();
const multer = require('multer');
const rateLimit = require('express-rate-limit');
const Redis = require('ioredis');
const { body, validationResult } = require('express-validator');
const winston = require('winston');

// 配置日志
const logger = winston.createLogger({
    level: 'info',
    format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.json()
    ),
    transports: [
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});

// 配置Redis缓存
const redis = new Redis();

// 配置速率限制
const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15分钟
    max: 100 // 限制每个IP 100个请求
});

const app = express();
app.use(cors());
app.use(express.json());
app.use(limiter);

// 配置文件上传
const upload = multer({
    storage: multer.memoryStorage(),
    limits: {
        fileSize: 5 * 1024 * 1024 // 限制5MB
    }
});

// 数据库配置
const db = new sqlite3.Database('places.db', (err) => {
    if (err) {
        logger.error('数据库连接错误:', err);
        return;
    }
    logger.info('已连接到SQLite数据库');

    // 创建表
    db.run(`
        CREATE TABLE IF NOT EXISTS places (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            category TEXT,
            longitude REAL NOT NULL,
            latitude REAL NOT NULL,
            description TEXT,
            attributes TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    `);
});

// 缓存中间件
const cacheMiddleware = async (req, res, next) => {
    const cacheKey = `places:${req.originalUrl}`;
    try {
        const cachedData = await redis.get(cacheKey);
        if (cachedData) {
            return res.json(JSON.parse(cachedData));
        }
        next();
    } catch (error) {
        logger.error('缓存错误:', error);
        next();
    }
};

// 验证中间件
const validatePlace = [
    body('name').notEmpty().trim().escape(),
    body('longitude').isFloat(),
    body('latitude').isFloat(),
    body('category').optional().trim().escape(),
    body('description').optional().trim().escape(),
    body('attributes').optional().isArray()
];

// 获取所有地点
app.get('/api/places', cacheMiddleware, (req, res) => {
    db.all('SELECT * FROM places', async (err, rows) => {
        if (err) {
            logger.error('获取地点列表错误:', err);
            return res.status(500).json({
                status: 'error',
                message: err.message
            });
        }

        const places = rows.map(row => ({
            ...row,
            attributes: JSON.parse(row.attributes || '[]')
        }));

        // 设置缓存
        await redis.setex(`places:${req.originalUrl}`, 300, JSON.stringify({
            status: 'success',
            data: places
        }));

        res.json({
            status: 'success',
            data: places
        });
    });
});

// 创建地点
app.post('/api/places', validatePlace, (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        return res.status(400).json({
            status: 'error',
            message: '验证错误',
            errors: errors.array()
        });
    }

    const { name, category, longitude, latitude, description, attributes } = req.body;
    const attributesJson = JSON.stringify(attributes || []);

    db.run(`
        INSERT INTO places (name, category, longitude, latitude, description, attributes)
        VALUES (?, ?, ?, ?, ?, ?)
    `, [name, category, longitude, latitude, description, attributesJson],
    function(err) {
        if (err) {
            logger.error('创建地点错误:', err);
            return res.status(500).json({
                status: 'error',
                message: err.message
            });
        }

        // 清除缓存
        redis.del('places:/api/places');

        res.json({
            status: 'success',
            data: {
                id: this.lastID,
                name,
                category,
                longitude,
                latitude,
                description,
                attributes: attributes || []
            }
        });
    });
});

// 获取单个地点
app.get('/api/places/:id', cacheMiddleware, (req, res) => {
    db.get('SELECT * FROM places WHERE id = ?', [req.params.id], async (err, row) => {
        if (err) {
            logger.error('获取地点详情错误:', err);
            return res.status(500).json({
                status: 'error',
                message: err.message
            });
        }

        if (!row) {
            return res.status(404).json({
                status: 'error',
                message: '地点不存在'
            });
        }

        const place = {
            ...row,
            attributes: JSON.parse(row.attributes || '[]')
        };

        // 设置缓存
        await redis.setex(`places:${req.originalUrl}`, 300, JSON.stringify({
            status: 'success',
            data: place
        }));

        res.json({
            status: 'success',
            data: place
        });
    });
});

// 更新地点
app.put('/api/places/:id', validatePlace, (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        return res.status(400).json({
            status: 'error',
            message: '验证错误',
            errors: errors.array()
        });
    }

    const { name, category, longitude, latitude, description, attributes } = req.body;
    const attributesJson = JSON.stringify(attributes || []);

    db.run(`
        UPDATE places
        SET name = ?, category = ?, longitude = ?, latitude = ?,
            description = ?, attributes = ?
        WHERE id = ?
    `, [name, category, longitude, latitude, description, attributesJson, req.params.id],
    function(err) {
        if (err) {
            logger.error('更新地点错误:', err);
            return res.status(500).json({
                status: 'error',
                message: err.message
            });
        }

        if (this.changes === 0) {
            return res.status(404).json({
                status: 'error',
                message: '地点不存在'
            });
        }

        // 清除缓存
        redis.del(`places:/api/places/${req.params.id}`);
        redis.del('places:/api/places');

        res.json({
            status: 'success',
            data: {
                id: parseInt(req.params.id),
                name,
                category,
                longitude,
                latitude,
                description,
                attributes: attributes || []
            }
        });
    });
});

// 删除地点
app.delete('/api/places/:id', (req, res) => {
    db.run('DELETE FROM places WHERE id = ?', [req.params.id], function(err) {
        if (err) {
            logger.error('删除地点错误:', err);
            return res.status(500).json({
                status: 'error',
                message: err.message
            });
        }

        if (this.changes === 0) {
            return res.status(404).json({
                status: 'error',
                message: '地点不存在'
            });
        }

        // 清除缓存
        redis.del(`places:/api/places/${req.params.id}`);
        redis.del('places:/api/places');

        res.json({
            status: 'success'
        });
    });
});

// 导入地点
app.post('/api/places/import', upload.single('file'), (req, res) => {
    if (!req.file) {
        return res.status(400).json({
            status: 'error',
            message: '没有上传文件'
        });
    }

    try {
        const places = JSON.parse(req.file.buffer.toString());
        
        db.serialize(() => {
            db.run('BEGIN TRANSACTION');

            const stmt = db.prepare(`
                INSERT INTO places (name, category, longitude, latitude, description, attributes)
                VALUES (?, ?, ?, ?, ?, ?)
            `);

            places.forEach(place => {
                stmt.run(
                    place.name,
                    place.category,
                    place.longitude,
                    place.latitude,
                    place.description,
                    JSON.stringify(place.attributes || [])
                );
            });

            stmt.finalize();

            db.run('COMMIT', err => {
                if (err) {
                    logger.error('导入数据错误:', err);
                    return res.status(500).json({
                        status: 'error',
                        message: err.message
                    });
                }

                // 清除缓存
                redis.del('places:/api/places');

                res.json({
                    status: 'success'
                });
            });
        });
    } catch (err) {
        logger.error('解析导入文件错误:', err);
        res.status(400).json({
            status: 'error',
            message: '无效的JSON格式'
        });
    }
});

// 导出地点
app.get('/api/places/export', (req, res) => {
    db.all('SELECT * FROM places', (err, rows) => {
        if (err) {
            logger.error('导出数据错误:', err);
            return res.status(500).json({
                status: 'error',
                message: err.message
            });
        }

        const places = rows.map(row => ({
            ...row,
            attributes: JSON.parse(row.attributes || '[]')
        }));

        res.json(places);
    });
});

// 搜索地点
app.get('/api/places/search', (req, res) => {
    const { keyword, category } = req.query;
    let query = 'SELECT * FROM places WHERE 1=1';
    const params = [];

    if (keyword) {
        query += ' AND (name LIKE ? OR description LIKE ?)';
        params.push(`%${keyword}%`, `%${keyword}%`);
    }

    if (category) {
        query += ' AND category = ?';
        params.push(category);
    }

    db.all(query, params, (err, rows) => {
        if (err) {
            logger.error('搜索地点错误:', err);
            return res.status(500).json({
                status: 'error',
                message: err.message
            });
        }

        const places = rows.map(row => ({
            ...row,
            attributes: JSON.parse(row.attributes || '[]')
        }));

        res.json({
            status: 'success',
            data: places
        });
    });
});

// 错误处理中间件
app.use((err, req, res, next) => {
    logger.error('应用错误:', err);
    res.status(500).json({
        status: 'error',
        message: '服务器内部错误'
    });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    logger.info(`服务器运行在端口 ${PORT}`);
}); 